<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/5/14 0014
 * Time: 下午 3:35
 */

namespace App\Common;

use App\Utility\DBTools;
use App\Enum\SysEnum;
use App\Utility\RedisTools;
use App\Utility\BaseEnum;
use EasySwoole\EasySwoole\ServerManager;

/**
 * TODO 线程执行操作类
 * 
 * 
 * @author XCH
 */
class PorcessComm
{
    protected static $logger_tablename = 'qc_user_logs';               //写日志表名
    
    /**
     * TODO 需要启动的FUNCTION列表配置（自动载入执行线程操作）
     * TODO 格式：启动函数名 => 时间间隔(单位为/每分)
     * @var array
     */
    const PORCESS_START_FUNCTIONS = [
        'startLogsPorcess' => 3 ,
        'startAgentsPorcess' => 2 ,
        'startGameNoticePorcess' => 1,
    ];
    
    
    /**
     * TODO 启动写日志线程处理工作
     * @param number $everyMinute
     */
    public static function startLogsPorcess($everyMinute = 2){
        $nowStamp = BaseEnum::getNowTime(FALSE);
        $nowMinute = date("i", $nowStamp);
        //TODO 日志每3分种更新一次
        if($nowMinute % $everyMinute == 0){
            BaseEnum::Logger("记录线程[startLogsPorcess]启动：当前分钟数-{$nowMinute},日志每3分种更新一次 ");
            self::writeLoggerToDB(self::$logger_tablename);
        }
    }
    
    /**
     * TODO 启动代理线统计线程处理工作
     * @param number $everyMinute
     */
    public static function startAgentsPorcess($everyMinute = 2){
        $nowStamp = BaseEnum::getNowTime(FALSE);
        $nowMinute = date("i", $nowStamp);
        
        //TODO 日志每3分种更新一次
        if($nowMinute % $everyMinute == 0){
            BaseEnum::Logger("记录线程[startAgentsPorcess]启动：当前分钟数-{$nowMinute},日志每{$everyMinute}分种更新一次 ");
            SumComm::sumALLAgentLineData();                     //#####第一次就调用######所有代理的运营数据
        }
    }
    
    /**
     * TODO 启动每个游戏的公告通知
     * @param number $everyMinute
     */
    public static function startGameNoticePorcess($everyMinute = 1){
        BaseEnum::Logger("记录线程[GameNoticePorcess]启动：频率  ----> 1 分钟 ；");
        
        //TODO 游戏公告中奖信息每1分种刷新一次最新的数据是否推送出去
        
        self::pushALLGameSuccessNotices();                     //#####第一次就调用######所有代理的运营数据
    }
    
    /*************************************************************线程实现方案************************************************************/
    
    //TODO 查询每个游戏的成功数据处理游戏通知操作（推到大厅所有用户）
    private static function pushALLGameSuccessNotices(){
        
        $notPushData = [];
        //查询最新的数据
        $noticeKey = SysEnum::USERWIN_NOTICE_KEY."*";
        $allkeys = RedisTools::Pool_keys($noticeKey);   //模糊查询
        if(!empty($allkeys)){
            foreach ($allkeys as $one_krval){
                $mygid = intval(substr($one_krval, strrpos($one_krval, ':') + 1));
                
                //TODO　取远程的数据处理；
                $onekeys = RedisTools::Pool_hAllKeys($one_krval);
                $max_hakey = !empty($onekeys) ? max($onekeys) :FALSE; //取最后一条是否推送处理
                if(!$max_hakey) continue;
                $max_havalue = RedisTools::Pool_hGet($one_krval, $max_hakey); //最后一条的值处理
                $max_haobj = !empty($max_havalue) ? json_decode($max_havalue,TRUE) : FALSE ;
                
                //TODO 远程处理还没有推送过的数据
                $content = $max_haobj['content'] ?? FALSE;
                if(!empty($max_haobj) && isset($max_haobj['push_stauts']) && intval($max_haobj['push_stauts']) !== 1 && !empty($content)) {
                    //TODO 消息未发出的内容
                    $notPushData[] = ["gameId"=> $mygid,'unitkey'=> $max_haobj['timestamp'] ?? 0,"content"=> $content] ;
                    $max_haobj['push_stauts']= 1;
                    RedisTools::Pool_hSet($one_krval, $max_hakey,json_encode($max_haobj)); //最后一条的值处理为成功的
                }
            }
        }
        //TODO 调用 API 发出数据
        if(!empty($notPushData)){
            $sURL = BaseComm::getSiteReqURL();
            $linkUrls = ["{$sURL}/api/pushLists?gameId=0&ptype=NOTICE&pushdata=".json_encode($notPushData)];      //请求URL地址
            BaseComm::doMoreRequest($linkUrls);
            BaseEnum::Logger("REQUEST[Notice]未完成：HTTP请求  ----> ". json_encode($linkUrls));
        }
        return FALSE;
    }
    
    //TODO 日志写入DB
    private static function writeLoggerToDB($logTableName = 'qc_user_logs' ){
        $redisobj = new RedisTools();
        $redisobj->select(0);
        $DBObj = DBTools::getPoolDB();
        $DBObj->startTransaction();
        try{
            $logs = $redisobj->hGetAll(SysEnum::USERLOGS_KEY);
            $data = [];
            foreach ($logs as $key => $log) {
                //取出一条删除一条
                $data[$key] = json_decode($log,true);
                $res = $redisobj->hDel(SysEnum::USERLOGS_KEY,$key);
                //BaseEnum::Logger('删除rediskey'.$res,'user-login');
            }
            //批量插入
            $res = $DBObj->insertMulti($logTableName, $data);
            if ($res){
                BaseEnum::Logger('执行日志写DB操作成功','user-login');
                $DBObj->commit();
            }else{
                //不成功一条一条添回
                foreach ($data as $key=>$log){
                    $redisobj->hSet(SysEnum::USERLOGS_KEY,$key,json_encode($log,JSON_UNESCAPED_UNICODE));
                }
            }
        }catch(\Throwable $throwable){
            $DBObj -> rollback();
        }finally{
            DBTools::destPoolDB($DBObj);   //释放Pool
        }
    }
}